<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>按钮点击需求1.0</title>
</head>
<style>
    #modal {
        height: 200px;
        width: 200px;
        line-height: 200px;
        position: fixed;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        border: 1px solid black;
        text-align: center;
    }
</style>
<body>
	<button id='open'>点击打开</button>
	<button id='close'>关闭弹窗</button>
</body>
<script>
// 弹窗创建逻辑，这里我们复用了单例模式面试题的例子
    const Modal = (function() {
    	let modal = null
    	return function() {
            if(!modal) {
            	modal = document.createElement('div')
            	modal.innerHTML = '您还未登录哦~'
            	modal.id = 'modal'
            	modal.style.display = 'none'
            	document.body.appendChild(modal)
            }
            return modal
    	}
    })()
    /*
    -----------------------------------------------------------------------------------------ES5 函数式实现---------------------
    // 1. 原有逻辑：弹窗功能（抽离为独立函数）
    function openModal() {
      const modal = new Modal(); // 文章中定义的单例弹窗（确保只创建一次）
      modal.style.display = 'block';
    }
    
    // 2. 新增逻辑：按钮状态修改（拆分后整合，符合单一职责）
    function changeButtonText() {
      const btn = document.getElementById('open');
      btn.innerText = '快去登录';
    }
    function disableButton() {
      const btn = document.getElementById('open');
      btn.disabled = true;
    }
    // 装饰逻辑：整合新增功能
    function changeButtonStatus() {
      changeButtonText();
      disableButton();
    }
    // 点击打开按钮展示模态框
    document.getElementById('open').addEventListener('click', function() {
        // 未点击则不创建modal实例，避免不必要的内存占用
        openModal();
        changeButtonStatus();
    })
    */
// 1. 原有对象：按钮类（含弹窗逻辑）
    class OpenButton {
      onClick() {
        const modal = new Modal();
        modal.style.display = 'block';
      }
    }

// 2. 装饰器类：持有原按钮实例，拓展功能
    class ButtonDecorator {
      constructor(openButton) {
        this.openButton = openButton; // 保存原对象引用，避免修改原对象
      }

      // 装饰后的核心方法：先执行原逻辑，再执行新增逻辑
      onClick() {
        this.openButton.onClick(); // 原有逻辑
        this.changeButtonStatus(); // 新增逻辑
      }

      // 新增逻辑拆分（单一职责）
      changeButtonStatus() {
        this.changeButtonText();
        this.disableButton();
      }
      changeButtonText() { 
        const btn = document.getElementById('open');
        btn.innerText = btn.innerText === '点击打开' ? '快去登录' : '点击打开';
     }
      disableButton() {
        const btn = document.getElementById('open');
        btn.disabled = btn.disabled === true ? false : true;
       }
    }

    // 3. 使用装饰器
    const openButton = new OpenButton();
    const decoratedButton = new ButtonDecorator(openButton);
    document.getElementById('open').addEventListener('click', () => {
      decoratedButton.onClick(); // 执行装饰后的逻辑
    });

    // 点击关闭按钮隐藏模态框
    document.getElementById('close').addEventListener('click', function() {
    	const modal = document.getElementById('modal')
    	if(modal) {
    	    modal.style.display = 'none'
            decoratedButton.changeButtonStatus()
    	}
    })  
 // ---------------------------------------------------------------------日志打印装饰器--------------------
function add(a, b) {
  return a + b;
}
function multiply(a, b) {
  return a * b;
}

// 2. 日志装饰器：接收原函数，返回装饰后的函数
function logDecorator(fn) {
  // 返回新函数，用...args保留原函数所有参数，apply保持this指向

  return function(...args) {
    // 装饰逻辑：打印输入参数
    console.log(`输入参数：${args.join(', ')}`);
    // 执行原函数，获取结果
    const result = fn.apply(this, args);
    // 装饰逻辑：打印执行结果
    console.log(`执行结果：${result}`);
    // 返回原函数结果，不改变原函数的返回值
    return result;
  };
}
// 3. 使用装饰器
const decoratedAdd = logDecorator(add);
const decoratedMultiply = logDecorator(multiply);

// 测试
decoratedAdd(2, 3); // 输出：输入参数：2, 3 → 执行结果：5 → 返回5
decoratedMultiply(4, 5); // 输出：输入参数：4, 5 → 执行结果：20 → 返回20


</script>
</html>
